; (load "stream.scm")

(define (sqrt-improve guess x)
  (define (average x y) (/ (+ x y) 2))
  (average guess (/ x guess)))

(define (sqrt-stream x)
  (define guesses
    (cons-stream 1.0 
                 (stream-map (lambda (guess) (sqrt-improve guess x))
                             guesses)))
  guesses)

(define foo (sqrt-stream 2))
(for-each (lambda (x) (display-line (stream-ref foo x))) (range 0 10))
(newline)
; 1.
; 1.5
; 1.4166666666666665
; 1.4142156862745097
; 1.4142135623746899
; 1.414213562373095
; 1.414213562373095
; 1.414213562373095
; 1.414213562373095
; 1.414213562373095

(define (pi-summands n)
  (cons-stream (/ 1.0 n)
               (stream-map - (pi-summands (+ n 2)))))
; copy from 3.55
(define (partial-sums s)
  (cons-stream (stream-car s)
               (add-streams (stream-cdr s)
                            (partial-sums s))))
(define pi-stream
  (scale-stream (partial-sums (pi-summands 1)) 4))

(for-each (lambda (x) (display-line (stream-ref pi-stream x))) (range 0 10))
(newline)
; 4.
; 2.666666666666667
; 3.466666666666667
; 2.8952380952380956
; 3.3396825396825403
; 2.9760461760461765
; 3.2837384837384844
; 3.017071817071818
; 3.2523659347188767
; 3.0418396189294032


(define (euler-transform s)
  (let ((s0 (stream-ref s 0))
        (s1 (stream-ref s 1))
        (s2 (stream-ref s 2)))
    (cons-stream (- s2 (/ (square (- s2 s1))
                          (+ s0 (* -2 s1) s2)))
                 (euler-transform (stream-cdr s)))))

(for-each (lambda (x) (display-line (stream-ref (euler-transform pi-stream) x))) (range 0 10))
(newline)
; 3.166666666666667
; 3.1333333333333337
; 3.1452380952380956
; 3.13968253968254
; 3.1427128427128435
; 3.1408813408813416
; 3.142071817071818
; 3.1412548236077655
; 3.1418396189294033
; 3.141406718496503

(define (make-tableau transform s)
  (cons-stream s
               (make-tableau transform
                             (transform s))))

(define (accelerated-sequence transform s)
  (stream-map stream-car (make-tableau transform s)))

(define accelerated-pi (accelerated-sequence euler-transform pi-stream))

(for-each (lambda (x) (display-line (stream-ref (euler-transform accelerated-pi) x))) (range 0 10))
(newline)

; 3.141359363702097
; 3.141588717725456
; 3.1415926256369255
; 3.1415926534273817
; 3.1415926535887038
; 3.1415926535897727
; 3.1415926535897953
; 3.141592653589795